package com.cdn.nodes.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.cdn.common.core.exception.ServiceException;
import com.cdn.common.core.utils.SSHUtils;
import com.cdn.common.redis.service.RedisService;
import com.cdn.nodes.domain.EdgeClustersNodes;
import com.cdn.nodes.domain.EdgeNodes;
import com.cdn.nodes.domain.EdgeNodesSshPort;
import com.cdn.nodes.domain.EdgeSshNode;
import com.cdn.nodes.domain.dto.EdgeNodeSshDTO;
import com.cdn.nodes.domain.dto.EdgeNodesAddDTO;
import com.cdn.nodes.domain.dto.EdgeNodesInstallDTO;
import com.cdn.nodes.domain.qo.EdgeNodesQO;
import com.cdn.nodes.domain.vo.EdgeNodeSshAndPortVO;
import com.cdn.nodes.domain.vo.EdgeNodesVO;
import com.cdn.nodes.mapper.*;
import com.cdn.nodes.service.IEdgeNodesService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;

/**
 * 边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等Service业务层处理
 * 
 * @author Cinzia
 * @date 2024-12-20
 */
@Service
public class EdgeNodesServiceImpl implements IEdgeNodesService
{
    @Resource
    private EdgeNodesMapper edgeNodesMapper;

    @Resource
    private EdgeClustersNodesMapper edgeClustersNodesMapper;

    @Resource
    private RedisService redisService;

    @Resource
    private EdgeNodesSshPortMapper edgeNodesSshPortMapper;

    @Resource
    private EdgeSshNodeMapper edgeSshNodeMapper;

    @Resource
    private EdgeIpListMapper edgeIpListMapper;

    @Resource
    private EdgeIpNodeMapper edgeIpNodeMapper;

    @Value("${jar-file-path}")
    private String jarFilePath;


    /**
     * 查询边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等
     * 
     * @param id 边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等主键
     * @return 边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等
     */
    @Override
    public EdgeNodes selectEdgeNodesById(Long id)
    {
        return edgeNodesMapper.selectEdgeNodesById(id);
    }

    /**
     * 查询边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等列表
     * 
     * @param edgeNodesQO 边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等
     * @return 边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等
     */
    @Override
    public List<EdgeNodesVO> selectEdgeNodesList(EdgeNodesQO edgeNodesQO)
    {
        List<EdgeNodesVO> edgeNodesVOS = edgeNodesMapper.selectEdgeNodesList(edgeNodesQO);
        for (EdgeNodesVO edgeNodesVO : edgeNodesVOS) {
            Long nodeId = edgeNodesVO.getNodeId();
            JSONObject result =redisService.getCacheObject("node:"+nodeId);
            if(result!=null){
                edgeNodesVO.setCpu((BigDecimal) result.get("cpu"));
                edgeNodesVO.setMemory((BigDecimal) result.get("memory"));
                edgeNodesVO.setDownstreamBandwidth((Long) result.get("downstreamBandwidth"));
                edgeNodesVO.setConnections((Integer) result.get("connections"));
                edgeNodesVO.setLoad((BigDecimal) result.get("load"));
            }
        }
        // 从redis获取节点
        return edgeNodesVOS;
    }

    /**
     * 新增边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等
     *
     * @param edgeNodesAddDTO 边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public Long insertEdgeNodes(EdgeNodesAddDTO edgeNodesAddDTO) {

        EdgeNodes edgeNodes = new EdgeNodes();
        BeanUtils.copyProperties(edgeNodesAddDTO, edgeNodes);
        int result = edgeNodesMapper.insertEdgeNodes(edgeNodes);
        if (result > 0) {
            // 将节点ID插入集群节点中间表
            EdgeClustersNodes edgeClustersNodes = new EdgeClustersNodes();
            edgeClustersNodes.setNodeId(edgeNodes.getId());
            edgeClustersNodes.setClusterId(edgeNodesAddDTO.getClusterId());
            edgeClustersNodesMapper.insertEdgeClustersNodes(edgeClustersNodes);
        }

        // 将认证Id还有节点Id插入节点ssh认证中间表
        if (edgeNodesAddDTO.getSshAuthId() != null) {
            EdgeSshNode edgeSshNode = new EdgeSshNode();
            edgeSshNode.setNodeId(edgeNodes.getId());
            edgeSshNode.setSshId(edgeNodesAddDTO.getSshAuthId());
            edgeSshNodeMapper.insertEdgeSshNode(edgeSshNode);
        }

        // 将ssh端口插入节点ssh认证端口中间表
        EdgeNodesSshPort edgeNodesSshPort = new EdgeNodesSshPort();
        edgeNodesSshPort.setNodeId(edgeNodes.getId());
        edgeNodesSshPort.setPort(edgeNodesAddDTO.getSshPort());
        edgeNodesSshPortMapper.insertEdgeNodesSshPort(edgeNodesSshPort);

        return edgeNodes.getId();
    }

    /**
     * 修改边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等
     * 
     * @param edgeNodes 边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等
     * @return 结果
     */
    @Override
    public int updateEdgeNodes(EdgeNodes edgeNodes)
    {
        return edgeNodesMapper.updateEdgeNodes(edgeNodes);
    }

    /**
     * 批量删除边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等
     * 
     * @param ids 需要删除的边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等主键
     * @return 结果
     */
    @Override
    public int deleteEdgeNodesByIds(Long[] ids)
    {
        return edgeNodesMapper.deleteEdgeNodesByIds(ids);
    }

    /**
     * 删除边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等信息
     * 
     * @param id 边缘节点，用于记录每个CDN边缘节点的详细信息，包括名称、IP地址、区域、集群、SSH信息等主键
     * @return 结果
     */
    @Override
    public int deleteEdgeNodesById(Long id)
    {
        return edgeNodesMapper.deleteEdgeNodesById(id);
    }

    /**
     * 根据节点Id获取DNS线路
     * @param nodeId
     * @return
     */
    @Override
    public String getDnsLineByNodeId(Long nodeId) {
        return edgeNodesMapper.selectDnsLineByNodeId(nodeId);
    }

    @Override
    public int enableNodeStatusByNodeId(Long nodeId) {
        return edgeNodesMapper.enableNodeStatusByNodeId(nodeId);
    }

    @Override
    public int DeactivatedNodeStatusByNodeId(Long nodeId) {
        return edgeNodesMapper.DeactivatedNodeStatusByNodeId(nodeId);
    }

    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public int deleteNodeByNodeId(Long nodeId) {
        try {
            // 删除集群节点关联
            edgeClustersNodesMapper.deleteEdgeClustersNodesByNodeId(nodeId);

            // 删除SSH认证信息和节点关联
            edgeSshNodeMapper.deleteEdgeSshNodeByNodeId(nodeId);

            Long ipAddressId = edgeIpNodeMapper.selectIpAddressId(nodeId);

            // 删除节点IP信息关联
            edgeIpNodeMapper.deleteEdgeIpNodeByNodeId(nodeId);

            // 删除节点主机信息
            edgeIpListMapper.deleteEdgeIpListById(ipAddressId);

            // 删除节点主机端口信息
            edgeNodesSshPortMapper.deleteEdgeNodesSshPortByNodeId(nodeId);

            // 删除节点信息
            edgeNodesMapper.deleteEdgeNodesById(nodeId);

            return 1;
        } catch (Exception e) {
            throw new ServiceException("删除节点失败");
        }
    }

    @Override
    public EdgeNodeSshAndPortVO getNodeSshAndPort(Long nodeId) {
        return edgeNodesMapper.getNodeSshAndPort(nodeId);
    }

    @Override
    public int installNode(EdgeNodesInstallDTO edgeNodesInstallDTO) {
        // 根据节点Id获取主机认证
        EdgeNodeSshDTO edgeNodeSshDTO = edgeNodesMapper.getNodeSsh(edgeNodesInstallDTO.getNodeId());
        // 主机用户名
        String sshUser = edgeNodeSshDTO.getSshUser();
        // 主机密钥
        String sshKey = edgeNodeSshDTO.getSshKey();
        // 主机地址
        String sshHost = edgeNodesInstallDTO.getIpAddress();
        // 主机端口
        Integer port = edgeNodesInstallDTO.getPort();

        // 安装目录
        String installDir = edgeNodesInstallDTO.getInstallDir();

        // 在远程主机上创建安装目录
        String createDirCommand = "sudo mkdir -p " + installDir + " && sudo chmod 777 " + installDir;
        SSHUtils.executeRemoteCreateDirCommand(sshHost, sshUser, sshKey, port, createDirCommand);

        // 上传 JAR 文件
        SSHUtils.uploadJarFile(sshHost, sshUser, sshKey,port, jarFilePath, installDir);

        // 检测节点是否已安装JDK8环境
        String checkJavaVersionCommand = "java -version";
        String javaVersionOutput = SSHUtils.executeRemoteCheckJavaVersionCommand(sshHost, sshUser, sshKey, port, checkJavaVersionCommand);

        if (javaVersionOutput.contains("1.8")) {
            // JDK8已安装，执行启动命令
            String startCommand = String.format(
                    "java -jar %s/cdn-modules-nodes-client.jar --rpc.endpoints[0]=%s --rpc.nodeId=%d",
                    installDir, sshHost, edgeNodesInstallDTO.getNodeId()
            );
            SSHUtils.executeRemoteJarCommand(sshHost, sshUser, sshKey, port, startCommand);
        } else {
            // JDK8未安装，执行安装后启动命令
            String installJavaCommand = "sudo apt install -y openjdk-8-jre-headless";
            SSHUtils.executeRemoteInstallJavaCommand(sshHost, sshUser, sshKey, port, installJavaCommand);
            String startCommand = String.format(
                    "java -jar %s/%s --rpc.endpoints[0]=%s --rpc.nodeId=%d",
                    installDir, jarFilePath, sshHost, edgeNodesInstallDTO.getNodeId()
            );
            SSHUtils.executeRemoteJarCommand(sshHost, sshUser, sshKey, port, startCommand);
            return -1;
        }

        return 0;
    }

    @Override
    public List<String> getNodeLine(Long[] nodeId) {
        return edgeNodesMapper.getNodeLine(nodeId);
    }

}
